import math
import numpy as np


class DataSet():
    def __init__(self):
        # 二维向量，横轴是分片，纵轴是时隙
        self.bitratelevel = []
        self.bitrateInfo = []
        self.buffer = []
        self.FovRecord = []
        self.rebuffer_time = []
        self.throughput = []
        self.pause_total = []

    def Fetch_data_from_file(self, filepath, filename):
        pos = []
        file = filepath + filename
        with open(file, 'r') as file_to_read:
            while True:
                lines = file_to_read.readline()  # 整行读取数据
                if not lines:
                    break
                p_tmp = [float(i) for i in lines.split(',')]  # 将整行数据分割处理，如果分割符是空格，括号里就不用传入参数，如果是逗号， 则传入‘，'字符。
                pos.append(p_tmp)  # 添加新读取的数据
            pos = np.array(pos)
        if filename == "bitrateLevel.txt":
            self.bitratelevel = pos
        elif filename == "bitrateInfo.txt":
            self.bitrateInfo = pos
        elif filename == "throughput.txt":
            self.throughput = pos
        elif filename == "buffer.txt":
            self.buffer = pos
        elif filename == "FovRecord.txt":
            self.FovRecord = pos
        elif filename == "pause_total.txt":
            self.pause_total = pos
        elif filename == "rebuffer_time.txt":
            self.rebuffer_time = pos



MAX_Q = 8 # 动态去找吧
MIN_Q = 1



# state_rate_mapping = {0: 8,
#                       1: 24,
#                       2: 36,
#                       3: 48}  # 单位MBps
# state_rate_mapping = {0: 0.2,
#                            1: 2,
#                            2: 12,
#                            3: 24}
# state_rate_mapping = {0: 0.2,
#                            1: 0.8,
#                            2: 2.4,
#                            3: 12}
# state_rate_mapping = {0: 0.8,
#                            1: 2.4,
#                            2: 7.2,
#                            3: 12}

state_rate_mapping = {0: 0.15,
                           1: 2.4,
                           2: 6.4,
                           3: 16}

def calculate_Parameter():
    S1 = state_rate_mapping[0]
    S2 = state_rate_mapping[1]
    alpha = (S1*utilities(1) - S2*utilities(0)) / (S2 - S1) # α = S1υ2 −S2υ1/S2 −S1
    V = (MAX_Q - MIN_Q)/(utilities(3) - alpha)
    rp = (utilities(3)*MIN_Q - alpha*MAX_Q)/(MAX_Q - MIN_Q)
    return V,rp


def utilities(bitrate_level):
    return math.log(state_rate_mapping[bitrate_level]/state_rate_mapping[0] ,math.e) # ln(Sm/S1)


def decide_m(V,rp,Q,throughput):
    choose = []
    Tk_list = []
    for i in range(4):
        Tk = state_rate_mapping[i] / throughput
        Tk_list.append(Tk)
        tmp = 10/(Q-Tk) if Q-Tk > 0 else (Q-Tk)
        value = (V*utilities(i) + V*rp - Q)/state_rate_mapping[i]
        value = value if Q-Tk>0 else value/2
        choose.append( value )
    # x = max(choose)
    max_value = max(choose)
    m = np.argmax(choose)
    # m = 0
    # for i in range(4):
    #     if choose[i] == max_value:
    #         m = i

    return max_value,m


def run(throughput):
    V,rp = calculate_Parameter()
    slot_dict = {}
    slot = 0
    step = 0
    buffer = 0
    rebuffer_event = 0
    Q = 0
    while step < len(throughput):  # 先加载完吧
        am = 0
        value, _ = decide_m(V, rp, Q)  # 这里的Q是上一时刻的Q,决策出了m

        if value > 0: # 可以下载后面一个1s的segment

            _, m = decide_m(V, rp, Q)
            am = 1
            # print(step)
            Tk = state_rate_mapping[m]/throughput[step] # Tk，下载时间，也就是Slot持续时间

            step += 1
            slot += Tk

            buffer += 1-Tk

        else:
            Tk = 1
            slot += Tk # 这个1 是那个不加载时的deta
            buffer = buffer - Tk



        # 到这里slot结束了，然后计算新的Q
        if Q - Tk < 0:
            rebuffer_event = Q-Tk
        Q = max(Q - Tk, 0) + am

        slot_dict[step] = (m,rebuffer_event)

        rebuffer_event = 0
    return slot_dict


if __name__ == "__main__":
    dataset = DataSet()
    dataset.Fetch_data_from_file("data_train/1/", "FovRecord.txt")
    dataset.Fetch_data_from_file("data_train/1/", "throughput.txt")
    throughput_total = dataset.throughput/8000000
    FoV = dataset.FovRecord
    throughput = [[],[],[],[],[],[]]
    for throughput_step in throughput_total:
        for i in range(6):
            throughput[i].append(throughput_step[i])

    result0 = run(throughput[0])
    result1 = run(throughput[1])
    result2 = run(throughput[2])
    result3 = run(throughput[3])
    result4 = run(throughput[4])
    result5 = run(throughput[5])



    FoV_Adjacent = {0: [2, 3, 4, 5],
                         1: [2, 3, 4, 5],
                         2: [0, 1, 4, 5],
                         3: [0, 1, 4, 5],
                         4: [0, 1, 2, 3],
                         5: [0, 1, 2, 3]}
    # 现在的逻辑是第一个FoV为1的当成主视角，也就是最高优先级 主视角0.8 主视角相邻的tile中 有1的给0.2，0的给0.1
    artificial_range_1s = {}
    range_temp = [0, 1, 2, 3, 4, 5]
    main_perspective = 0
    main_near = []
    artificial_range_2s = {}
    for i in range_temp:
        if FoV[i].astype(int) == 1:
            # count = list(FoV[self.video_slot + 1].astype(int)).count(1)
            artificial_range_1s[i] = 0.8  # 主视野内权重为0.8
            range_temp.remove(i)
            main_perspective = i
            for j in FoV_Adjacent[i]:
                range_temp.remove(j)
                if FoV[j].astype(int) == 1:
                    artificial_range_1s[j] = 0.5
                    main_near.append(j)
                else:
                    artificial_range_1s[j] = 0.2

        artificial_range_1s[range_temp[0]] = 0

    bitrate_level_total = 0
    # 乘哪个FoV这个判断直接在state中考量，，等一下，有点问题

    action = [result0[0][0],result1[0][0],result2[0][0],result3[0][0],result4[0][0],result5[0][0]]
    for i in range(6):  # 6个面
        bitrate_level_total += action[i] * artificial_range_1s[i]

    # 帧内平滑度
    # 考虑FoV的东西，这个平滑度考虑主视角和其他四片的差异
    smoothness_within_frame = 0
    for i in FoV_Adjacent[main_perspective]:
        if i in main_near:
            smoothness_within_frame += abs(action[main_perspective] - action[i])
        else:
            smoothness_within_frame += abs(0.5 * (action[main_perspective] - action[i]))

    rebuffer_event = result0[0][1]+result1[0][1]+result2[0][1]+result3[0][1]+result4[0][1]+result5[0][1]



    alpha = 0.2
    beta = 0.8
    gamma = 2
    reward = alpha * bitrate_level_total - beta * smoothness_within_frame - gamma * rebuffer_event

    print(reward)